const express = require("express");
const fileUpload = require("express-fileupload");
const fs = require("fs");
const path = require("path");
const { v4: uuidv4 } = require("uuid");
const { Product, Project, Jmx } = require("../db");
const config = require("../../config");

const router = express.Router();
router.use(fileUpload());

router.post("/product/createProduct", async (req, res) => {
    try {
        const { productName, productSummary } = req.body;
        let product = await Product.findOne({ where: { product_name: productName.toUpperCase() } });
        if (product) {
            return res.customResponse(400, "产品名称已存在", {});
        }
        product = await Product.create({
            product_name: productName.toUpperCase(),
            product_summary: productSummary
        });
        product = product.toJSON();
        const response = {
            productId: product.id,
            productName: product.product_name,
            productSummary: product.product_summary,
            createdAt: product.created_at,
            updatedAt: product.updated_at
        };
        res.customResponse(200, "success", response);
    } catch (error) {
        console.log(error);
        res.customResponse(500, error.message, {});
    }
});

router.post("/product/getProductList", async (req, res) => {
    try {
        let products = await Product.findAll({
            attributes: [
                ["id", "productId"],
                ["product_name", "productName"],
                ["product_summary", "productSummary"],
                ["created_at", "createdAt"],
                ["updated_at", "updatedAt"]
            ]
        });
        products = products.map(product => product.toJSON());
        const response = products;
        res.customResponse(200, "success", response);
    } catch (error) {
        console.log(error);
        res.customResponse(500, error.message, {});
    }
});

router.post("/project/createProject", async (req, res) => {
    try {
        const { projectName, projectSummary } = req.body;
        let project = await Project.findOne({ where: { project_name: projectName.toUpperCase() } });
        if (project) {
            return res.customResponse(400, "项目名称已存在", {});
        }
        project = await Project.create({
            project_name: projectName.toUpperCase(),
            project_summary: projectSummary
        });
        project = project.toJSON();
        const response = {
            projectId: project.id,
            projectName: project.project_name,
            projectSummary: project.project_summary,
            createdAt: project.created_at,
            updatedAt: project.updated_at
        };
        res.customResponse(200, "success", response);
    } catch (error) {
        console.log(error);
        res.customResponse(500, error.message, {});
    }
});

router.post("/project/getProjectList", async (req, res) => {
    try {
        let projects = await Project.findAll({
            attributes: [
                ["id", "projectId"],
                ["project_name", "projectName"],
                ["project_summary", "projectSummary"],
                ["created_at", "createdAt"],
                ["updated_at", "updatedAt"]
            ]
        });
        projects = projects.map(project => project.toJSON());
        const response = projects;
        res.customResponse(200, "success", response);
    } catch (error) {
        console.log(error);
        res.customResponse(500, error.message, {});
    }
});

router.post("/uploadHarFiles", async (req, res) => {
    try {
        if (!(req.files && req.files.harFiles)) {
            return res.customResponse(400, "未上传HAR文件", {});
        }
        const productId = req.body.productId || null;
        const projectId = req.body.projectId || null;
        const harFiles = Array.isArray(req.files.harFiles) ? req.files.harFiles : [req.files.harFiles];
        const uuid = uuidv4();
        const harPath = path.resolve(config.path.data, "har", uuid);
        fs.mkdirSync(harPath, { recursive: true });
        for (const harFile of harFiles) {
            const harFileName = decodeURIComponent(harFile.name);
            const harFilePath = path.resolve(harPath, harFileName);
            await harFile.mv(harFilePath);
            await Jmx.create({
                uuid: uuid,
                product_id: productId,
                project_id: projectId,
                test_plan_name: path.parse(harFilePath).name,
                har_file_path: path.join("data", "har", uuid, harFileName),
            })
        }
        const response = {
            uuid: uuid
        };
        res.customResponse(200, "success", response);
    } catch (error) {
        console.log(error);
        res.customResponse(500, error.message, {});
    }
});

router.post("/getHarList", async (req, res) => {
    try {
        const productId = req.body.productId || null;
        const projectId = req.body.projectId || null;
        let hars = await Jmx.findAll({
            attributes: [
                "id",
                "uuid",
                ["test_plan_name", "testPlanName"],
                ["har_file_path", "harFilePath"],
                ["created_at", "createdAt"],
                ["updated_at", "updatedAt"]
            ],
            include: [
                {
                    model: Product,
                    attributes: [["product_name", "productName"]],
                    required: false,
                },
                {
                    model: Project,
                    attributes: [["project_name", "projectName"]],
                    required: false,
                }
            ],
            where: {
                ...(productId ? { product_id: productId } : {}),
                ...(projectId ? { project_id: projectId } : {})
            }
        });
        hars = hars.map(har => har.toJSON());
        hars = hars.reduce((acc, cur) => {
            if (!acc[cur.uuid]) {
                acc[cur.uuid] = {
                    uuid: cur.uuid,
                    productName: cur.Product && cur.Product.productName,
                    projectName: cur.Project && cur.Project.projectName,
                    harList: [{
                        testPlanName: cur.testPlanName,
                        harFilePath: cur.harFilePath,
                        createdAt: cur.createdAt,
                        updatedAt: cur.updatedAt
                    }],
                    createdAt: hars.filter(har => har.uuid === cur.uuid).reduce((acc, cur) => {
                        return cur.createdAt < acc ? cur.createdAt : acc
                    }, cur.createdAt),
                    updatedAt: hars.filter(har => har.uuid === cur.uuid).reduce((acc, cur) => {
                        return cur.updatedAt > acc ? cur.updatedAt : acc
                    }, cur.updatedAt)
                };
            } else {
                acc[cur.uuid].harList.push({
                    testPlanName: cur.testPlanName,
                    harFilePath: cur.harFilePath,
                    createdAt: cur.createdAt,
                    updatedAt: cur.updatedAt
                });
            }
            return acc;
        }, {});
        const response = Object.keys(hars).map(key => hars[key]).sort((har1, har2) => {
            if (har1.updatedAt === har2.updatedAt) {
                return har2.createdAt - har1.createdAt;
            }
            return har2.updatedAt - har1.updatedAt;
        });
        res.customResponse(200, "success", response);
    } catch (error) {
        console.log(error);
        res.customResponse(500, error.message, {});
    }
});

module.exports = router;
